/*
 * Copyright (c) 2017, cxy7.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.b3log.solo.controller.console;

import java.net.URLDecoder;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.b3log.solo.Keys;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Sign;
import org.b3log.solo.model.Skin;
import org.b3log.solo.module.util.QueryResults;
import org.b3log.solo.renderer.JSONRenderer;
import org.b3log.solo.service.LangPropsService;
import org.b3log.solo.service.OptionMgmtService;
import org.b3log.solo.service.OptionQueryService;
import org.b3log.solo.service.PreferenceMgmtService;
import org.b3log.solo.service.PreferenceQueryService;
import org.b3log.solo.service.ServiceException;
import org.b3log.solo.service.UserQueryService;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Preference console request processing.
 *
 * @author <a href="http://cxy7.com">XyCai</a>
 * @version 1.2.0.9, Nov 15, 2016
 * @since 0.4.0
 */
@Controller
public class PreferenceConsole {

	/**
	 * Logger.
	 */
	private static Logger logger = LoggerFactory.getLogger(PreferenceConsole.class);

	/**
	 * Preference query service.
	 */
	@Autowired
	private PreferenceQueryService preferenceQueryService;

	/**
	 * Preference management service.
	 */
	@Autowired
	private PreferenceMgmtService preferenceMgmtService;

	/**
	 * Option management service.
	 */
	@Autowired
	private OptionMgmtService optionMgmtService;

	/**
	 * Option query service.
	 */
	@Autowired
	private OptionQueryService optionQueryService;

	/**
	 * User query service.
	 */
	@Autowired
	private UserQueryService userQueryService;

	/**
	 * Language service.
	 */
	@Autowired
	private LangPropsService langPropsService;

	/**
	 * Preference URI prefix.
	 */
	private static final String PREFERENCE_URI_PREFIX = "/console/preference/";

	/**
	 * Gets reply template.
	 *
	 * <p>
	 * Renders the response with a json object, for example,
	 * 
	 * <pre>
	 * {
	 *     "sc": boolean,
	 *     "replyNotificationTemplate": {
	 *         "subject": "",
	 *         "body": ""
	 *     }
	 * }
	 * </pre>
	 * </p>
	 *
	 * @param request
	 *            the specified http servlet request
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = "/console/reply/notification/template", method = RequestMethod.GET)
	public void getReplyNotificationTemplate(final HttpServletRequest request, final HttpServletResponse response)
			throws Exception {
		if (!userQueryService.isLoggedIn(request, response)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();
		try {
			final JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
			final JSONObject ret = new JSONObject();
			renderer.setJSONObject(ret);
			ret.put("replyNotificationTemplate", replyNotificationTemplate);
			ret.put(Keys.STATUS_CODE, true);
		} catch (final Exception e) {
			logger.error(e.getMessage(), e);
			final JSONObject jsonObject = QueryResults.defaultResult();
			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, langPropsService.get("getFailLabel"));
		}
		renderer.render(request, response);
	}

	/**
	 * Updates reply template.
	 *
	 * @param request
	 *            the specified http servlet request, for example,
	 * 
	 *            <pre>
	 * {
	 *     "replyNotificationTemplate": {
	 *         "subject": "",
	 *         "body": ""
	 *     }
	 * }
	 *            </pre>
	 *
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = "/console/reply/notification/template", method = RequestMethod.PUT)
	public void updateReplyNotificationTemplate(final HttpServletRequest request, final HttpServletResponse response, @RequestParam String body) throws Exception {
		if (!userQueryService.isLoggedIn(request, response)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();
		try {
			body = URLDecoder.decode(body, "UTF-8");final JSONObject requestJSONObject = new JSONObject(body);

			final JSONObject replyNotificationTemplate = requestJSONObject.getJSONObject("replyNotificationTemplate");

			preferenceMgmtService.updateReplyNotificationTemplate(replyNotificationTemplate);

			final JSONObject ret = new JSONObject();

			ret.put(Keys.STATUS_CODE, true);
			ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));

			renderer.setJSONObject(ret);
		} catch (final Exception e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, langPropsService.get("updateFailLabel"));
		}
		renderer.render(request, response);
	}

	/**
	 * Gets signs.
	 *
	 * <p>
	 * Renders the response with a json object, for example,
	 * 
	 * <pre>
	 * {
	 *     "sc": boolean,
	 *     "signs": [{
	 *         "oId": "",
	 *         "signHTML": ""
	 *      }, ...]
	 * }
	 * </pre>
	 * </p>
	 *
	 * @param request
	 *            the specified http servlet request
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = "/console/signs/", method = RequestMethod.GET)
	public void getSigns(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
		if (!userQueryService.isLoggedIn(request, response)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();

		try {
			final JSONObject preference = preferenceQueryService.getPreference();

			final JSONArray signs = new JSONArray();

			final JSONArray allSigns = // includes the empty sign(id=0)
					new JSONArray(preference.getString(Option.ID_C_SIGNS));

			for (int i = 1; i < allSigns.length(); i++) { // excludes the empty
															// sign
				signs.put(allSigns.getJSONObject(i));
			}

			final JSONObject ret = new JSONObject();

			renderer.setJSONObject(ret);

			ret.put(Sign.SIGNS, signs);
			ret.put(Keys.STATUS_CODE, true);
		} catch (final Exception e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, langPropsService.get("getFailLabel"));
		}
		renderer.render(request, response);
	}

	/**
	 * Gets preference.
	 *
	 * <p>
	 * Renders the response with a json object, for example,
	 * 
	 * <pre>
	 * {
	 *     "sc": boolean,
	 *     "preference": {
	 *         "mostViewArticleDisplayCount": int,
	 *         "recentCommentDisplayCount": int,
	 *         "mostUsedTagDisplayCount": int,
	 *         "articleListDisplayCount": int,
	 *         "articleListPaginationWindowSize": int,
	 *         "mostCommentArticleDisplayCount": int,
	 *         "externalRelevantArticlesDisplayCount": int,
	 *         "relevantArticlesDisplayCount": int,
	 *         "randomArticlesDisplayCount": int,
	 *         "blogTitle": "",
	 *         "blogSubtitle": "",
	 *         "localeString": "",
	 *         "timeZoneId": "",
	 *         "skinName": "",
	 *         "skinDirName": "",
	 *         "skins": "[{
	 *             "skinName": "",
	 *             "skinDirName": ""
	 *         }, ....]",
	 *         "noticeBoard": "",
	 *         "footerContent": "",
	 *         "htmlHead": "",
	 *         "adminEmail": "",
	 *         "metaKeywords": "",
	 *         "metaDescription": "",
	 *         "enableArticleUpdateHint": boolean,
	 *         "signs": "[{
	 *             "oId": "",
	 *             "signHTML": ""
	 *         }, ...]",
	 *         "allowVisitDraftViaPermalink": boolean,
	 *         "allowRegister": boolean,
	 *         "version": "",
	 *         "articleListStyle": "", // Optional values: "titleOnly"/"titleAndContent"/"titleAndAbstract"
	 *         "commentable": boolean,
	 *         "feedOutputMode: "" // Optional values: "abstract"/"full"
	 *         "feedOutputCnt": int
	 *     }
	 * }
	 * </pre>
	 * </p>
	 *
	 * @param request
	 *            the specified http servlet request
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = PREFERENCE_URI_PREFIX, method = RequestMethod.GET)
	public void getPreference(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
		if (!userQueryService.isAdminLoggedIn(request)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();
		try {
			final JSONObject preference = preferenceQueryService.getPreference();

			if (null == preference) {
				renderer.setJSONObject(QueryResults.defaultResult());
				renderer.render(request, response);
				return;
			}

			String footerContent = "";
			final JSONObject opt = optionQueryService.getOptionById(Option.ID_C_FOOTER_CONTENT);
			if (null != opt) {
				footerContent = opt.optString(Option.OPTION_VALUE);
			}
			preference.put(Option.ID_C_FOOTER_CONTENT, footerContent);

			final JSONObject ret = new JSONObject();

			renderer.setJSONObject(ret);
			ret.put(Option.CATEGORY_C_PREFERENCE, preference);
			ret.put(Keys.STATUS_CODE, true);
		} catch (final Exception e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, langPropsService.get("getFailLabel"));
		}
		renderer.render(request, response);
	}

	/**
	 * Updates the preference by the specified request.
	 *
	 * @param request
	 *            the specified http servlet request, for example,
	 * 
	 *            <pre>
	 * {
	 *     "preference": {
	 *         "mostViewArticleDisplayCount": int,
	 *         "recentCommentDisplayCount": int,
	 *         "mostUsedTagDisplayCount": int,
	 *         "articleListDisplayCount": int,
	 *         "articleListPaginationWindowSize": int,
	 *         "mostCommentArticleDisplayCount": int,
	 *         "externalRelevantArticlesDisplayCount": int,
	 *         "relevantArticlesDisplayCount": int,
	 *         "randomArticlesDisplayCount": int,
	 *         "blogTitle": "",
	 *         "blogSubtitle": "",
	 *         "skinDirName": "",
	 *         "localeString": "",
	 *         "timeZoneId": "",
	 *         "noticeBoard": "",
	 *         "footerContent": "",
	 *         "htmlHead": "",
	 *         "metaKeywords": "",
	 *         "metaDescription": "",
	 *         "enableArticleUpdateHint": boolean,
	 *         "signs": [{
	 *             "oId": "",
	 *             "signHTML": ""
	 *         }, ...],
	 *         "allowVisitDraftViaPermalink": boolean,
	 *         "allowRegister": boolean,
	 *         "articleListStyle": "",
	 *         "commentable": boolean,
	 *         "feedOutputMode: "",
	 *         "feedOutputCnt": int
	 *     }
	 * }, see {@link org.b3log.solo.model.Preference} for more details
	 *            </pre>
	 *
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = PREFERENCE_URI_PREFIX, method = RequestMethod.PUT)
	public void updatePreference(final HttpServletRequest request, final HttpServletResponse response, @RequestParam String body) throws Exception {
		if (!userQueryService.isAdminLoggedIn(request)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();

		try {
			body = URLDecoder.decode(body, "UTF-8");final JSONObject requestJSONObject = new JSONObject(body);

			final JSONObject preference = requestJSONObject.getJSONObject(Option.CATEGORY_C_PREFERENCE);

			final JSONObject ret = new JSONObject();

			renderer.setJSONObject(ret);

			if (isInvalid(preference, ret)) {
				renderer.render(request, response);
				return;
			}

			preferenceMgmtService.updatePreference(preference);

			final Cookie cookie = new Cookie(Skin.SKIN, preference.getString(Skin.SKIN_DIR_NAME));
			cookie.setPath("/");
			response.addCookie(cookie);

			ret.put(Keys.STATUS_CODE, true);
			ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
		} catch (final ServiceException e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, e.getMessage());
		}
		renderer.render(request, response);
	}

	/**
	 * Gets Qiniu preference.
	 *
	 * <p>
	 * Renders the response with a json object, for example,
	 * 
	 * <pre>
	 * {
	 *     "sc": boolean,
	 *     "qiniuAccessKey": "",
	 *     "qiniuSecretKey": "",
	 *     "qiniuDomain": "",
	 *     "qiniuBucket": ""
	 * }
	 * </pre>
	 * </p>
	 *
	 * @param request
	 *            the specified http servlet request
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = PREFERENCE_URI_PREFIX + "qiniu", method = RequestMethod.GET)
	public void getQiniuPreference(final HttpServletRequest request, final HttpServletResponse response)
			throws Exception {
		if (!userQueryService.isAdminLoggedIn(request)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();

		try {
			final JSONObject qiniu = optionQueryService.getOptions(Option.CATEGORY_C_QINIU);

			if (null == qiniu) {
				renderer.setJSONObject(QueryResults.defaultResult());
				renderer.render(request, response);
				return;
			}

			final JSONObject ret = new JSONObject();

			renderer.setJSONObject(ret);
			ret.put(Option.CATEGORY_C_QINIU, qiniu);
			ret.put(Keys.STATUS_CODE, true);
		} catch (final Exception e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, langPropsService.get("getFailLabel"));
		}
		renderer.render(request, response);
	}

	/**
	 * Updates the Qiniu preference by the specified request.
	 *
	 * @param request
	 *            the specified http servlet request, for example,
	 * 
	 *            <pre>
	 * {
	 *     "qiniuAccessKey": "",
	 *     "qiniuSecretKey": "",
	 *     "qiniuDomain": "",
	 *     "qiniuBucket": ""
	 * }, see {@link org.b3log.solo.model.Option} for more details
	 *            </pre>
	 *
	 * @param response
	 *            the specified http servlet response
	 * @param context
	 *            the specified http request context
	 * @throws Exception
	 *             exception
	 */
	@RequestMapping(value = PREFERENCE_URI_PREFIX + "qiniu", method = RequestMethod.PUT)
	public void updateQiniu(final HttpServletRequest request, final HttpServletResponse response, @RequestParam String body) throws Exception {
		if (!userQueryService.isAdminLoggedIn(request)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		final JSONRenderer renderer = new JSONRenderer();

		try {
			body = URLDecoder.decode(body, "UTF-8");final JSONObject requestJSONObject = new JSONObject(body);

			final String accessKey = requestJSONObject.optString(Option.ID_C_QINIU_ACCESS_KEY).trim();
			final String secretKey = requestJSONObject.optString(Option.ID_C_QINIU_SECRET_KEY).trim();
			String domain = requestJSONObject.optString(Option.ID_C_QINIU_DOMAIN).trim();
			final String bucket = requestJSONObject.optString(Option.ID_C_QINIU_BUCKET).trim();

			final JSONObject ret = new JSONObject();
			renderer.setJSONObject(ret);

			if (StringUtils.isNotBlank(domain) && !StringUtils.endsWith(domain, "/")) {
				domain += "/";
			}

			final JSONObject accessKeyOpt = new JSONObject();
			accessKeyOpt.put(Keys.OBJECT_ID, Option.ID_C_QINIU_ACCESS_KEY);
			accessKeyOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_QINIU);
			accessKeyOpt.put(Option.OPTION_VALUE, accessKey);
			final JSONObject secretKeyOpt = new JSONObject();
			secretKeyOpt.put(Keys.OBJECT_ID, Option.ID_C_QINIU_SECRET_KEY);
			secretKeyOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_QINIU);
			secretKeyOpt.put(Option.OPTION_VALUE, secretKey);
			final JSONObject domainOpt = new JSONObject();
			domainOpt.put(Keys.OBJECT_ID, Option.ID_C_QINIU_DOMAIN);
			domainOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_QINIU);
			domainOpt.put(Option.OPTION_VALUE, domain);
			final JSONObject bucketOpt = new JSONObject();
			bucketOpt.put(Keys.OBJECT_ID, Option.ID_C_QINIU_BUCKET);
			bucketOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_QINIU);
			bucketOpt.put(Option.OPTION_VALUE, bucket);

			optionMgmtService.addOrUpdateOption(accessKeyOpt);
			optionMgmtService.addOrUpdateOption(secretKeyOpt);
			optionMgmtService.addOrUpdateOption(domainOpt);
			optionMgmtService.addOrUpdateOption(bucketOpt);

			ret.put(Keys.STATUS_CODE, true);
			ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
		} catch (final ServiceException e) {
			logger.error(e.getMessage(), e);

			final JSONObject jsonObject = QueryResults.defaultResult();

			renderer.setJSONObject(jsonObject);
			jsonObject.put(Keys.MSG, e.getMessage());
		}
		renderer.render(request, response);
	}

	/**
	 * Checks whether the specified preference is invalid and sets the specified
	 * response object.
	 *
	 * @param preference
	 *            the specified preference
	 * @param responseObject
	 *            the specified response object
	 * @return {@code true} if the specified preference is invalid, returns
	 *         {@code false} otherwise
	 */
	private boolean isInvalid(final JSONObject preference, final JSONObject responseObject) {
		responseObject.put(Keys.STATUS_CODE, false);

		final StringBuilder errMsgBuilder = new StringBuilder('[' + langPropsService.get("paramSettingsLabel"));

		errMsgBuilder.append(" - ");

		String input = preference.optString(Option.ID_C_EXTERNAL_RELEVANT_ARTICLES_DISPLAY_CNT);

		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("externalRelevantArticlesDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_RELEVANT_ARTICLES_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("relevantArticlesDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_RANDOM_ARTICLES_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("randomArticlesDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_MOST_COMMENT_ARTICLE_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("indexMostCommentArticleDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_MOST_VIEW_ARTICLE_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("indexMostViewArticleDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_RECENT_COMMENT_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("indexRecentCommentDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_MOST_USED_TAG_DISPLAY_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("indexTagDisplayCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_ARTICLE_LIST_DISPLAY_COUNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("pageSizeLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("windowSizeLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		input = preference.optString(Option.ID_C_FEED_OUTPUT_CNT);
		if (!isNonNegativeInteger(input)) {
			errMsgBuilder.append(langPropsService.get("feedOutputCntLabel")).append("]  ")
					.append(langPropsService.get("nonNegativeIntegerOnlyLabel"));
			responseObject.put(Keys.MSG, errMsgBuilder.toString());
			return true;
		}

		return false;
	}

	/**
	 * Checks whether the specified input is a non-negative integer.
	 *
	 * @param input
	 *            the specified input
	 * @return {@code true} if it is, returns {@code false} otherwise
	 */
	private boolean isNonNegativeInteger(final String input) {
		try {
			return 0 <= Integer.valueOf(input);
		} catch (final Exception e) {
			return false;
		}
	}
}
